lib: Option<Path>,
bins: Vec<Path>,
examples: Vec<Path>,
+ tests: Vec<Path>,
}
impl Layout {
let mut lib = None;
let mut bins = vec!();
let mut examples = vec!();
+ let mut tests = vec!();
if root.join("src/lib.rs").exists() {
lib = Some(root.join("src/lib.rs"));
.map(|mut i| i.collect())
.map(|found| examples.push_all_move(found));
+ // support two styles of tests: src/test.rs or tests/*.rs
+ let _ = fs::readdir(&root.join("tests"))
+ .map(|v| v.move_iter())
+ .map(|i| i.filter(|f| f.extension_str() == Some("rs")))
+ .map(|mut i| i.collect())
+ .map(|found| tests.push_all_move(found));
+
+ if root.join("src/test.rs").exists() {
+ tests.push(root.join("src/test.rs"));
+ }
+
Layout {
lib: lib,
bins: bins,
examples: examples,
+ tests: tests,
}
}
type TomlLibTarget = TomlTarget;
type TomlBinTarget = TomlTarget;
type TomlExampleTarget = TomlTarget;
+type TomlTestTarget = TomlTarget;
/*
* TODO: Make all struct fields private
lib: Option<Vec<TomlLibTarget>>,
bin: Option<Vec<TomlBinTarget>>,
example: Option<Vec<TomlExampleTarget>>,
+ test: Option<Vec<TomlTestTarget>>,
dependencies: Option<HashMap<String, TomlDependency>>,
dev_dependencies: Option<HashMap<String, TomlDependency>>
}
}).collect())
}
+fn inferred_test_targets(layout: &Layout) -> Option<Vec<TomlTarget>> {
+ Some(layout.tests.iter().filter_map(|ex| {
+ let name = ex.filestem_str().map(|f| f.to_string());
+
+ name.map(|name| {
+ TomlTarget {
+ name: name,
+ crate_type: None,
+ path: Some(ex.display().to_string()),
+ test: None,
+ plugin: None,
+ }
+ })
+ }).collect())
+}
+
impl TomlManifest {
pub fn to_manifest(&self, source_id: &SourceId, layout: &Layout)
-> CargoResult<(Manifest, Vec<Path>)>
}).collect())
};
+ let tests = if self.test.is_none() || self.test.get_ref().is_empty() {
+ inferred_test_targets(layout)
+ } else {
+ Some(self.test.get_ref().iter().map(|t| {
+ t.clone()
+ }).collect())
+ };
+
// Get targets
let targets = normalize(lib.as_ref().map(|l| l.as_slice()),
bins.as_ref().map(|b| b.as_slice()),
examples.as_ref().map(|e| e.as_slice()),
+ tests.as_ref().map(|e| e.as_slice()),
&metadata);
if targets.is_empty() {
fn normalize(lib: Option<&[TomlLibTarget]>,
bin: Option<&[TomlBinTarget]>,
example: Option<&[TomlExampleTarget]>,
+ test: Option<&[TomlTestTarget]>,
metadata: &Metadata)
-> Vec<Target>
{
- log!(4, "normalizing toml targets; lib={}; bin={}; example={}", lib, bin, example);
+ log!(4, "normalizing toml targets; lib={}; bin={}; example={}; test={}",
+ lib, bin, example, test);
enum TestDep { Needed, NotNeeded }
}
}
+ fn test_targets(dst: &mut Vec<Target>, tests: &[TomlTestTarget],
+ default: |&TomlTestTarget| -> String) {
+ for test in tests.iter() {
+ let path = test.path.clone().unwrap_or_else(|| default(test));
+
+ let profile = &Profile::default_test();
+ {
+ dst.push(Target::test_target(test.name.as_slice(),
+ &Path::new(path.as_slice()),
+ profile));
+ }
+ }
+ }
+
let mut ret = Vec::new();
match (lib, bin) {
None => ()
}
+ match test {
+ Some(ref tests) => {
+ test_targets(&mut ret, tests.as_slice(),
+ |test| {
+ if test.name.as_slice() == "test" {
+ "src/test.rs".to_string()
+ } else {
+ format!("tests/{}.rs", test.name)
+ }});
+ },
+ None => ()
+ }
+
ret
}
compiling = COMPILING,
dir = p.root().display()).as_slice()));
})
+
+test!(external_test_explicit {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [[test]]
+ name = "test"
+ path = "src/test.rs"
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn get_hello() -> &'static str { "Hello" }
+
+ #[test]
+ fn internal_test() {}
+ "#)
+ .file("src/test.rs", r#"
+ extern crate foo;
+
+ #[test]
+ fn external_test() { assert_eq!(foo::get_hello(), "Hello") }
+ "#);
+
+ let output = p.cargo_process("cargo-test")
+ .exec_with_output().assert();
+ let out = str::from_utf8(output.output.as_slice()).assert();
+
+ let internal = "\
+running 1 test
+test internal_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured";
+ let external = "\
+running 1 test
+test external_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured";
+
+ let head = format!("{compiling} foo v0.0.1 (file:{dir})",
+ compiling = COMPILING, dir = p.root().display());
+
+ assert!(out == format!("{}\n\n{}\n\n\n{}\n\n", head, internal, external).as_slice() ||
+ out == format!("{}\n\n{}\n\n\n{}\n\n", head, external, internal).as_slice());
+})
+
+test!(external_test_implicit {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ "#)
+ .file("src/lib.rs", r#"
+ pub fn get_hello() -> &'static str { "Hello" }
+
+ #[test]
+ fn internal_test() {}
+ "#)
+ .file("src/test.rs", r#"
+ extern crate foo;
+
+ #[test]
+ fn external_test() { assert_eq!(foo::get_hello(), "Hello") }
+ "#);
+
+ let output = p.cargo_process("cargo-test")
+ .exec_with_output().assert();
+ let out = str::from_utf8(output.output.as_slice()).assert();
+
+ let internal = "\
+running 1 test
+test internal_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured";
+ let external = "\
+running 1 test
+test external_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured";
+
+ let head = format!("{compiling} foo v0.0.1 (file:{dir})",
+ compiling = COMPILING, dir = p.root().display());
+
+ assert!(out == format!("{}\n\n{}\n\n\n{}\n\n", head, internal, external).as_slice() ||
+ out == format!("{}\n\n{}\n\n\n{}\n\n", head, external, internal).as_slice());
+})